﻿
#ifndef PRECISION_TIME_H_
#define PRECISION_TIME_H_

#ifdef _MSC_VER
#include <Windows.h>

class PreciTimer
{
public:
    explicit PreciTimer(void) : q_freq(0), q_ocount(0)
    {
        LARGE_INTEGER lcount;
        if (QueryPerformanceFrequency(&lcount)) {
            q_freq = lcount.QuadPart;
        }

        reset();
    }

    ~PreciTimer(void) {}

    //
    void reset()
    {
        LARGE_INTEGER lcount;
        if (QueryPerformanceCounter(&lcount)) {
            q_ocount = lcount.QuadPart;
        }
        else {
            q_ocount = 0;
        }
    }

    long mscount() const
    {
        LARGE_INTEGER lcount;
        QueryPerformanceCounter(&lcount);
        return (long)(lcount.QuadPart * 1000UL / q_freq);
    }

    long uscount() const
    {
        LARGE_INTEGER lcount;
        QueryPerformanceCounter(&lcount);
        return (long)(lcount.QuadPart * 1000000UL / q_freq);
    }

    long mstick() const
    {
        LARGE_INTEGER lcount;
        QueryPerformanceCounter(&lcount);
        return (long)((lcount.QuadPart - q_ocount) * 1000UL / q_freq);
    }

    long ustick() const
    {
        LARGE_INTEGER lcount;
        QueryPerformanceCounter(&lcount);
        return (long)((lcount.QuadPart - q_ocount) * 1000000UL / q_freq);
    }

    long nstick() const
    {
        LARGE_INTEGER lcount;
        QueryPerformanceCounter(&lcount);
        return (long)((lcount.QuadPart - q_ocount) * 1000000000UL / q_freq);
    }

private:
    LONGLONG	q_freq;
    LONGLONG	q_ocount;
};

#else

#include <time.h>
#include <sys/time.h>

class PreciTimer
{
public:
    explicit PreciTimer(void) : q_orgTime(0) {}
    ~PreciTimer(void) {}

    void reset()
    {
        struct timespec time = { 0, 0 };
        clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time);
        q_orgTime = time.tv_nsec;
    }

    long mscount()
    {
        struct timespec time = { 0, 0 };
        clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time);
        return time.tv_nsec / 1000000L;
    }

    long uscount()
    {
        struct timespec time = { 0, 0 };
        clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time);
        return time.tv_nsec / 1000L;
    }

    long mstick()
    {
        struct timespec time = { 0, 0 };
        clock_gettime(CLOCK_REALTIME, &time);
        return (time.tv_nsec - q_orgTime) / 1000000L;
    }

    long ustick()
    {
        struct timespec time = { 0, 0 };
        clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time);
        return (time.tv_nsec - q_orgTime) / 1000L;
    }

    long nstick()
    {
        struct timespec time = { 0, 0 };
        clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time);
        return time.tv_nsec - q_orgTime;
    }

private:
    long q_orgTime;
};

#endif

#endif  // _HR_PRECISION_TIME_H_
